package com.daxidi.cn.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.daxidi.cn.config.wxconfig.WxPayConfig;
import com.daxidi.cn.entity.*;
import com.daxidi.cn.mapper.BillMapper;
import com.daxidi.cn.mapper.PayMapper;
import com.daxidi.cn.mapper.UserMapper;
import com.daxidi.cn.params.PayParamJSAPI;
import com.daxidi.cn.params.PayParamNative;
import com.daxidi.cn.service.*;
import com.daxidi.cn.utils.*;
import com.daxidi.cn.vo.WxMcoPayVo;
import com.github.wxpay.sdk.WXPayUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SimpleTimeZone;

/**
 * @author JiaLin
 * create 2020-11-06
 */
@Log4j
@Api(tags = "微信支付接口")
@Controller
@RequestMapping(value = "/api/v1/wxPay")
public class WxPayController {

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private WxPayConfig wxPayConfig;

    @Autowired
    private IBillService billService;

    @Autowired
    private IClerkService clerkService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IShopService shopService;

    @Autowired
    private BillMapper billMapper;

    @Autowired
    private PayMapper payMapper;

    @ApiOperation(value = "返回微信支付二维码图片地址", notes = "通过传用户编号、支付金额、商品描述、订单编号、商品编号返回支付二维码的URL")
    @ResponseBody
    @PostMapping(value = "/getCodePicUrl")
    public ReturnResult getCodePicUrl(@RequestBody PayParamNative payParamNative) {
        try {
            //获取微信支付回调地址
//            String str = wxPayService.unifiedOrder(payParamNative.getTotalFee(), payParamNative.getBody()
//                    , payParamNative.getOutTradeNo(), payParamNative.getProductId());
            String str = "";
            //二维码图片上传地址
            StringBuffer sb = new StringBuffer();
            sb.append("/home/jialin/file/img/qrCode/qrCode");
            //sb.append("D:\\qrCode\\qrCode");
            sb.append(payParamNative.getUserId());
            sb.append(".png");
            //上传图片
            QRCodeUtil.createQrCode(new FileOutputStream(new File(sb.toString())), str, 900, "png");
            //返回map
            HashMap map = new HashMap();
            map.put("code_url", "114.215.201.161/qrCode/qrCode" + payParamNative.getUserId() + ".png");
            log.info("===返回微信支付二维码成功！===" + map);
            return ReturnResultUtils.returnSuccess(map);
        } catch (Exception e) {
            log.error("===返回微信支付二维码失败！===");
            return ReturnResultUtils.returnFailMsg(415, "支付失败！" + e);
        }
    }

    @ApiOperation(value = "扫码枪支付")
    @ResponseBody
    @PostMapping(value = "/itemPay")
    public ReturnResult itemPay(@RequestParam String orderId) {
        try {
            //根据orderId获取bill对象
            log.info("===1.===根据orderId获取bill对象===");
            Bill bill = billService.selectBillByOrderId(Long.valueOf(orderId));
            if (ObjectUtils.isEmpty(bill)){
                log.info("bill对象查询为空");
            }
            //更新payAt时间
            bill.setPayAt(new Date());
            billMapper.updateById(bill);
            String discounted = bill.getDiscounted() + "";
            Double fee = Double.valueOf(discounted);
            fee = (double) Math.round(fee * 100) / 100;

            Integer totalFee = Integer.parseInt(new java.text.DecimalFormat("0").format(fee * 100));
            //根据clerkId获取shopId，获取shopName
            log.info("===2.===根据clerkId获取shopId，获取shopName===");
            Clerk clerk = clerkService.selectClerkById(bill.getClerkId());
            if (ObjectUtils.isEmpty(clerk)){
                log.info("clerk对象查询为空");
            }
            log.info("===3.===开始查询商铺===");
            Shop shop = shopService.selectShop(clerk.getShopId());
            if (ObjectUtils.isEmpty(shop)){
                log.info("shop对象查询为空");
            }
            String payBody = shop.getName();
            //根据memberId获取openId
            log.info("===4.===根据memberId获取openId===");
            User user = userService.selectUserByMemberId(bill.getMembeId());
            if (ObjectUtils.isEmpty(user)){
                log.info("user对象查询为空");
            }
            String openId = user.getOpenId();
            log.info("===5.===开始支付===");
            //获取微信支付mapResult
            Map<String, String> mapResult = wxPayService.unifiedOrderMcro(totalFee, payBody, orderId, openId);
            log.info("===返回微信支付成功！===" + mapResult);

            //以下内容是返回前端页面的json数据
            String prepay_id = "";//预支付id
            if ("SUCCESS".equals(mapResult.get("return_code")) && "SUCCESS".equals(mapResult.get("result_code"))) {
                prepay_id = mapResult.get("prepay_id");
            }
            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", "wx19b5a41593f4211b");
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("package", "prepay_id=" + prepay_id);
            payMap.put("signType", "MD5");
            payMap.put("timeStamp", System.currentTimeMillis()+"");

            String paySign = WXPayUtil.generateSignature(payMap, wxPayConfig.getKey());
            //String paySign = WxPayUtils.generateSignature(payMap, wxPayConfig.getKey());
            payMap.put("paySign", paySign);
            return ReturnResultUtils.returnSuccess(payMap);
        } catch (Exception e) {
            log.error("===返回微信支付失败！===" + e);
            e.printStackTrace();
            return ReturnResultUtils.returnFailMsg(415, "支付失败！" + e);
        }
    }

    //http://114.215.201.161:9082/wxPay/api/v1/jsapiPay
    @ApiOperation(value = "微信JSAPI支付")
    @ResponseBody
    @GetMapping(value = "/jsapiPay")
    public ReturnResult jsapiPay(@RequestParam String orderId) {
        try {
            //根据orderId获取bill对象
            log.info("===1.===根据orderId获取bill对象===");
            Bill bill = billService.selectBillByOrderId(Long.valueOf(orderId));
            if (ObjectUtils.isEmpty(bill)){
                log.info("bill对象查询为空");
            }
            //更新payAt时间
            bill.setPayAt(new Date());
            billMapper.updateById(bill);
            String discounted = bill.getDiscounted() + "";
            Double fee = Double.valueOf(discounted);
            fee = (double) Math.round(fee * 100) / 100;

            Integer totalFee = Integer.parseInt(new java.text.DecimalFormat("0").format(fee * 100));
            //根据clerkId获取shopId，来获取shopName
            log.info("===2.===根据clerkId获取shopId，获取shopName===");
            Clerk clerk = clerkService.selectClerkById(bill.getClerkId());
            if (ObjectUtils.isEmpty(clerk)){
                log.info("clerk对象查询为空");
            }
            log.info("===3.===开始查询商铺===");
            Shop shop = shopService.selectShop(clerk.getShopId());
            if (ObjectUtils.isEmpty(shop)){
                log.info("shop对象查询为空");
            }
            String payBody = "工会会员支付";
            //根据memberId获取openId
            log.info("===4.===根据memberId获取openId===");
            User user = userService.selectUserByMemberId(bill.getMembeId());
            if (ObjectUtils.isEmpty(user)){
                log.info("user对象查询为空");
            }
            String openId = user.getOpenId();
            log.info("===5.===开始支付===");
            //获取微信支付mapResult
            Map<String, String> mapResult = wxPayService.unifiedOrderJs(totalFee, payBody, orderId, openId);
            log.info("===返回微信支付成功！===" + mapResult);

            //以下内容是返回前端页面的json数据
            String prepay_id = "";//预支付id
            if ("SUCCESS".equals(mapResult.get("return_code")) && "SUCCESS".equals(mapResult.get("result_code"))) {
                prepay_id = mapResult.get("prepay_id");
            }
            Map<String, String> payMap = new HashMap<String, String>();
            payMap.put("appId", "wx19b5a41593f4211b");
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("package", "prepay_id=" + prepay_id);
            payMap.put("signType", "MD5");
            payMap.put("timeStamp", System.currentTimeMillis()+"");

            String paySign = WXPayUtil.generateSignature(payMap, wxPayConfig.getKey());
            //String paySign = WxPayUtils.generateSignature(payMap, wxPayConfig.getKey());
            payMap.put("paySign", paySign);
            return ReturnResultUtils.returnSuccess(payMap);
        } catch (Exception e) {
            log.error("===返回微信支付失败！===" + e);
            e.printStackTrace();
            return ReturnResultUtils.returnFailMsg(415, "支付失败！" + e);
        }
    }

    @ApiOperation(value = "返回微信支付二维码链接", notes = "通过传用户编号、支付金额、商品描述、订单编号、商品编号返回支付二维码的URL")
    @ResponseBody
    @PostMapping(value = "/getCodeUrl")
    public ReturnResult getCodeUrl() {
        try {
            //获取微信支付回调地址
            String str = wxPayService.unifiedOrder();
            log.info("===返回微信支付二维码成功！===" + str);
            HashMap map = new HashMap();
            map.put("code_url", str);
            return ReturnResultUtils.returnSuccess(map);
        } catch (Exception e) {
            log.error("===返回微信支付二维码失败！===");
            e.printStackTrace();
            return ReturnResultUtils.returnFailMsg(415, "支付失败！" + e);
        }
    }

    @ApiOperation(value = "JSAPI微信支付回调函数")
    @PostMapping(value = "/notifyUrls")
    public void notifyUrls(HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream inputStream = request.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuffer stringBuffer = new StringBuffer();
        String line;
        while (null != (line = bufferedReader.readLine())) {
            stringBuffer.append(line);
        }
        bufferedReader.close();
        inputStream.close();
        //xml格式转换map
        Map<String, String> resultMap = WxPayUtils.xmlToMap(stringBuffer.toString());
        log.info("===支付resultMap！=== " + resultMap);
        //验证签名
        if (WxPayUtils.checkSign(resultMap, wxPayConfig.getKey())) {
            String resultCode = resultMap.get("result_code");
            //支付成功，商户处理后同步返回给微信参数
            if ("SUCCESS".equals(resultCode)) {
                //支付成功的业务
                //更新订单状态为已支付
                String orderId = resultMap.get("out_trade_no");
                log.info("===支付orderId！=== " + orderId);
                QueryWrapper<Bill> wrapper2 = new QueryWrapper<>();
                wrapper2.eq("order_id", orderId);
                Bill bill = billMapper.selectOne(wrapper2);
                bill.setState(1);
                bill.setNotifyAt(new Date());
                billService.updateBillById(bill);
                //插入pay订单表数据
                Pay pay = new Pay();
                pay.setTransactionId(resultMap.get("transaction_id"));
                pay.setOpenId(resultMap.get("openid"));
                pay.setBankType(resultMap.get("bank_type"));
                pay.setFeeType(resultMap.get("fee_type"));
                pay.setMchId(resultMap.get("mch_id"));
                pay.setOutTradeNo(resultMap.get("out_trade_no"));
                pay.setAppId(resultMap.get("appid"));
                pay.setTotalFee(Integer.valueOf(resultMap.get("total_fee")));
                pay.setTradeType(resultMap.get("trade_type"));
                pay.setResultCode(resultMap.get("result_code"));
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                StringBuffer sb = new StringBuffer();
                String timeEnd = resultMap.get("time_end");
                sb.append(timeEnd.substring(0, 4));
                sb.append("-");
                sb.append(timeEnd.substring(4, 6));
                sb.append("-");
                sb.append(timeEnd.substring(6, 8));
                sb.append(" ");
                sb.append(timeEnd.substring(8, 10));
                sb.append(":");
                sb.append(timeEnd.substring(10, 12));
                sb.append(":");
                sb.append(timeEnd.substring(12, 14));
                pay.setTimeEnd(simpleDateFormat.parse(sb.toString()));
                pay.setIsSubscribe(resultMap.get("is_subscribe"));
                pay.setNotifyUrl(wxPayConfig.getNotifyUrl());
                pay.setBillId(bill.getId());
                pay.setCreatedAt(new Date());
                pay.setTimeStart(bill.getPayAt());
                payMapper.insert(pay);

                String noticeStr = setXML("SUCCESS", "OK");
                response.getWriter().write(noticeStr);
                inputStream.close();
                log.info("===支付成功！===");
            } else {
                String orderId = resultMap.get("out_trade_no");
                log.info("===支付orderId！=== " + orderId);
                QueryWrapper<Bill> wrapper2 = new QueryWrapper<>();
                wrapper2.eq("order_id", orderId);
                Bill bill = billMapper.selectOne(wrapper2);
                bill.setState(4);
                bill.setNotifyAt(new Date());
                billService.updateBillById(bill);
                //支付失败，插入pay表
                Pay pay = new Pay();
                pay.setTransactionId(resultMap.get("transaction_id"));
                pay.setOpenId(resultMap.get("openid"));
                pay.setBankType(resultMap.get("bank_type"));
                pay.setFeeType(resultMap.get("fee_type"));
                pay.setMchId(resultMap.get("mch_id"));
                pay.setOutTradeNo(resultMap.get("out_trade_no"));
                pay.setAppId(resultMap.get("appid"));
                pay.setTotalFee(Integer.valueOf(resultMap.get("total_fee")));
                pay.setResultCode(resultMap.get("result_code"));
                pay.setErrCode(resultMap.get("err_code"));
                pay.setErrCodeDes(resultMap.get("err_code_des"));
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                StringBuffer sb = new StringBuffer();
                String timeEnd = resultMap.get("time_end");
                sb.append(timeEnd.substring(0, 4));
                sb.append("-");
                sb.append(timeEnd.substring(4, 6));
                sb.append("-");
                sb.append(timeEnd.substring(6, 8));
                sb.append(" ");
                sb.append(timeEnd.substring(8, 10));
                sb.append(":");
                sb.append(timeEnd.substring(10, 12));
                sb.append(":");
                sb.append(timeEnd.substring(12, 14));
                pay.setTimeEnd(simpleDateFormat.parse(sb.toString()));
                pay.setIsSubscribe(resultMap.get("is_subscribe"));
                pay.setNotifyUrl(wxPayConfig.getNotifyUrl());
                pay.setBillId(bill.getId());
                pay.setCreatedAt(new Date());
                pay.setTimeStart(bill.getPayAt());
                payMapper.insert(pay);

                String noticeStr = setXML("FAIL", "FAIL");
                response.getWriter().write(noticeStr);
                inputStream.close();
                log.info("===支付失败！===");
            }
        }
    }

    @ApiOperation(value = "扫码枪微信支付回调函数")
    @PostMapping(value = "/notifyUrl")
    public ReturnResult notifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
        InputStream inputStream = request.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        StringBuffer stringBuffer = new StringBuffer();
        String line;
        while (null != (line = bufferedReader.readLine())) {
            stringBuffer.append(line);
        }
        bufferedReader.close();
        inputStream.close();
        //xml格式转换map
        Map<String, String> resultMap = WxPayUtils.xmlToMap(stringBuffer.toString());
        log.info("===支付resultMap！=== " + resultMap);
        //验证签名
        if (WxPayUtils.checkSign(resultMap, wxPayConfig.getKey())) {
            String resultCode = resultMap.get("result_code");
            //支付成功，商户处理后同步返回给微信参数
            if ("SUCCESS".equals(resultCode)) {
                //支付成功的业务
                //更新订单状态为已支付
                String orderId = resultMap.get("out_trade_no");
                log.info("===支付orderId！=== " + orderId);
                QueryWrapper<Bill> wrapper2 = new QueryWrapper<>();
                wrapper2.eq("order_id", orderId);
                Bill bill = billMapper.selectOne(wrapper2);
                bill.setState(1);
                bill.setNotifyAt(new Date());
                billService.updateBillById(bill);
                //插入pay订单表数据
                Pay pay = new Pay();
                pay.setTransactionId(resultMap.get("transaction_id"));
                pay.setOpenId(resultMap.get("openid"));
                pay.setBankType(resultMap.get("bank_type"));
                pay.setFeeType(resultMap.get("fee_type"));
                pay.setMchId(resultMap.get("mch_id"));
                pay.setOutTradeNo(resultMap.get("out_trade_no"));
                pay.setAppId(resultMap.get("appid"));
                pay.setTotalFee(Integer.valueOf(resultMap.get("total_fee")));
                pay.setTradeType(resultMap.get("trade_type"));
                pay.setResultCode(resultMap.get("result_code"));
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                StringBuffer sb = new StringBuffer();
                String timeEnd = resultMap.get("time_end");
                sb.append(timeEnd.substring(0, 4));
                sb.append("-");
                sb.append(timeEnd.substring(4, 6));
                sb.append("-");
                sb.append(timeEnd.substring(6, 8));
                sb.append(" ");
                sb.append(timeEnd.substring(8, 10));
                sb.append(":");
                sb.append(timeEnd.substring(10, 12));
                sb.append(":");
                sb.append(timeEnd.substring(12, 14));
                pay.setTimeEnd(simpleDateFormat.parse(sb.toString()));
                pay.setIsSubscribe(resultMap.get("is_subscribe"));
                pay.setNotifyUrl(wxPayConfig.getNotifyUrl());
                pay.setBillId(bill.getId());
                pay.setCreatedAt(new Date());
                pay.setTimeStart(bill.getPayAt());
                payMapper.insert(pay);

                String noticeStr = setXML("SUCCESS", "OK");
                response.getWriter().write(noticeStr);
                inputStream.close();
                log.info("===支付成功！===");
                WxMcoPayVo wxMcoPayVo = new WxMcoPayVo();
                wxMcoPayVo.setShopId(bill.getShopId());
                wxMcoPayVo.setMemberId(bill.getMembeId());
                wxMcoPayVo.setOrderId(bill.getOrderId());
                wxMcoPayVo.setWePayId(resultMap.get("transaction_id"));
                return ReturnResultUtils.returnSuccess(wxMcoPayVo);
            } else {
                String orderId = resultMap.get("out_trade_no");
                log.info("===支付orderId！=== " + orderId);
                QueryWrapper<Bill> wrapper2 = new QueryWrapper<>();
                wrapper2.eq("order_id", orderId);
                Bill bill = billMapper.selectOne(wrapper2);
                bill.setState(4);
                bill.setNotifyAt(new Date());
                billService.updateBillById(bill);
                //支付失败，插入pay表
                Pay pay = new Pay();
                pay.setTransactionId(resultMap.get("transaction_id"));
                pay.setOpenId(resultMap.get("openid"));
                pay.setBankType(resultMap.get("bank_type"));
                pay.setFeeType(resultMap.get("fee_type"));
                pay.setMchId(resultMap.get("mch_id"));
                pay.setOutTradeNo(resultMap.get("out_trade_no"));
                pay.setAppId(resultMap.get("appid"));
                pay.setTotalFee(Integer.valueOf(resultMap.get("total_fee")));
                pay.setResultCode(resultMap.get("result_code"));
                pay.setErrCode(resultMap.get("err_code"));
                pay.setErrCodeDes(resultMap.get("err_code_des"));
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                StringBuffer sb = new StringBuffer();
                String timeEnd = resultMap.get("time_end");
                sb.append(timeEnd.substring(0, 4));
                sb.append("-");
                sb.append(timeEnd.substring(4, 6));
                sb.append("-");
                sb.append(timeEnd.substring(6, 8));
                sb.append(" ");
                sb.append(timeEnd.substring(8, 10));
                sb.append(":");
                sb.append(timeEnd.substring(10, 12));
                sb.append(":");
                sb.append(timeEnd.substring(12, 14));
                pay.setTimeEnd(simpleDateFormat.parse(sb.toString()));
                pay.setIsSubscribe(resultMap.get("is_subscribe"));
                pay.setNotifyUrl(wxPayConfig.getNotifyUrl());
                pay.setBillId(bill.getId());
                pay.setCreatedAt(new Date());
                pay.setTimeStart(bill.getPayAt());
                payMapper.insert(pay);

                String noticeStr = setXML("FAIL", "FAIL");
                response.getWriter().write(noticeStr);
                inputStream.close();
                log.info("===支付失败！===");
                return ReturnResultUtils.returnFailMsg(20043, "支付失败！");
            }
        }
        return ReturnResultUtils.returnFailMsg(20044, "支付失败！验证签名错误！");
    }

    public static String setXML(String return_code, String return_msg) {
        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }

    @ResponseBody
    @PostMapping(value = "/createUrl")
    public ReturnResult createUrl(@RequestParam String url) throws Exception {
        String content = url;
        String filePath = "/home/jialin/file/img/qrCode/qrCode.png";
        //String filePath = "D://qrCode.png";
        try {
            QRCodeUtil.createQrCode(new FileOutputStream(new File(filePath)), content, 900, "png");
            return ReturnResultUtils.returnSuccess("创建二维码图片成功！");
        } catch (Exception e) {
            log.error("创建二维码图片失败！");
            return ReturnResultUtils.returnFailMsg(612, "创建二维码图片失败！");
        }
    }

}
